using System;
using System.Web;
using NHibernate;
using NHibernate.Context;

namespace Web.Extensions
{
	public class SessionScope : IDisposable
	{
		public SessionScope(ISessionFactory factory, HttpContextBase currentContext)
		{
			this.factory = factory;
			this.currentContext = currentContext;
			var session = factory.OpenSession();
			session.BeginTransaction();

			CurrentSessionContext.Bind(session);
		}

		public ISession Session
		{
			get { return factory.GetCurrentSession(); }
		}

		public void Dispose()
		{
			if (CurrentSessionContext.HasBind(factory))
			{
				using (var session = factory.GetCurrentSession())
				{
					bool shouldBeRolledBack = currentContext.Error != null;
					try
					{
						if (!shouldBeRolledBack)
						{
							if (session.Transaction != null && session.Transaction.IsActive)
								session.Transaction.Commit();
						}

						CurrentSessionContext.Unbind(factory);
					}
					catch
					{
						shouldBeRolledBack = true;
					}
					finally
					{
						if (shouldBeRolledBack)
						{
							if (session.Transaction != null && session.Transaction.IsActive)
								session.Transaction.Rollback();
						}
					}
					
				}
			}
		}

		readonly ISessionFactory factory;
		private readonly HttpContextBase currentContext;
	}
}